﻿using System;
using System.Collections.Generic;
using System.Text;

namespace SqliteDriver
{
	/*
		Class to encapsulate the growing requirements of foreign key management in the sql driver.
		This version handles a single field only, but may handle more later
		Done too quickly this is now a bit of a mess.
	*/
	internal class ForeignKey
	{
		internal ForeignKey(String fkeyTable, String fkeyField, String pkeyTable, String pkeyField)
		{
			this.fkeyTable = fkeyTable;
			this.fkeyField = fkeyField;
			this.pkeyTable = pkeyTable;
			this.pkeyField = pkeyField;
		}

		// in this version the tables and fields are joined with .
		internal ForeignKey(String fk, String pk)
		{
			String table, field;
			if (ParseTableField(fk, out table, out field) == false)
			{
				String message = String.Format("Error in ForeignKey fk argument format {0}. Expected was Table.Field", fk);
				throw new Exception (message);
			}
			this.fkeyTable = table;
			this.fkeyField = field;

			if (ParseTableField(pk, out table, out field) == false)
			{
				String message = String.Format("Error in ForeignKey pk argument format {0}. Expected was Table.Field", fk);
				throw new Exception (message);
			}
			this.pkeyTable = table;
			this.pkeyField = field;
		}

		static internal bool ParseTableField(string inputString, out string table, out string field)
		{
			table = field = "";
			int pos1 = inputString.IndexOf('.');
			if (pos1 == -1) return false; // no .
			// allow for schema tables in which case schema.table.field
			int pos2 = inputString.IndexOf('.', ++pos1);
			if (pos2 != -1) pos1 = pos2 + 1;
			table = inputString.Substring(0, pos1-1);
			field = inputString.Substring(pos1);
			return true;
		}

		internal String FkTable(bool sqlSafe) { return this.FormatTable(true, sqlSafe); }
		internal String PkTable(bool sqlSafe) { return this.FormatTable(false, sqlSafe); }

		internal String FkField(bool sqlSafe) { return (sqlSafe) ? "["+this.fkeyField+"]" : this.fkeyField; }
		internal String PkField(bool sqlSafe) { return (sqlSafe) ? "["+this.pkeyField+"]" : this.pkeyField;  }

		internal String GenerateFkName()
		{
			// build a name FK_fkTable_fkField_pkTable
			// note the replacement of . with _ when the schema is not dbo
			String fkeyName = String.Format("FK_{0}_{1}_{2}", this.FkTable(false).Replace(".", "_"), 
															this.FkField(false), 
															this.PkTable(false).Replace(".", "_"));
			return fkeyName.ToUpper();  // looks better in uc
		}
		
		internal String FkSchema {get{ return this.SchemaOf(this.fkeyTable, false); }}
		internal String PkSchema {get{ return this.SchemaOf(this.pkeyTable, false); }} 
		
		//String FormatFk(bool safe) { return FormatDefinition(true, safe); }
		////String FormatPk(bool safe) { return FormatDefinition(false, safe); }
		
		String SchemaOf(string table, bool wantDbo)
		{
			int pos = table.IndexOf(".");
			if (pos == -1) return (wantDbo) ? "dbo" : "";
			return table.Substring(0, pos);
		}

		String FormatTable(bool isFk, bool safe)
		{
			String table = (isFk) ? this.fkeyTable : this.pkeyTable;
			if (safe)
			{
				// This nonsense should be covered in SafeTableName
				//String schema = SchemaOf(table, false);
				//if (schema.Length > 0)
				//{
				//    table = table.Replace(schema+".", "");
				//    return String.Format("[{0}].[{1}]", schema, table);
				//}
				return String.Format("{0}", Helper.SafeTableName(table));
			}
			else
				return table;
		}

		//String FormatDefinition(bool isFk, bool safe)
		//{
		//    String table = (isFk) ? m_FkTable : m_PkTable;
		//    String field = (isFk) ? m_FkField : m_PkField;
		//    if (safe)
		//    {
		//        String schema = SchemaOf(table, false);
		//        if (schema.Length > 0)
		//        {
		//            table = table.Replace(schema+".", "");
		//            return String.Format("[{0}].[{1}].[{2}]", schema, table, field);
		//        }
		//        return String.Format("[{0}].[{1}]", table, field);
		//    }
		//    else
		//        return String.Format("{0}.{1}", table, field);
		////}

		String fkeyTable;
		String fkeyField;
		String pkeyTable;
		String pkeyField;
	}
}
